#include "leveleditor.h"
#include "buttonitem.h"
#include "canvas.h"
#include "level.h"
#include "point.h"
#include "line.h"
#include "saveleveldialog.h"

LevelEditor::LevelEditor(QGraphicsItem *parent, QGraphicsScene *scene) :
    QGraphicsItem(parent, scene), currentLevel(NULL)
{
    initScene();
    initEventSystem();
}

void LevelEditor::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{

}

QRectF LevelEditor::boundingRect() const
{
    return scene()->sceneRect();
}

void LevelEditor::initScene()
{
    background = new ImageItem(":/editor-background", QPoint(),
                               QPoint(ImageItem::BG_SIZE.width(),
                                      ImageItem::BG_SIZE.height()),
                               scene(), NULL);

    saveDialog = new SaveLevelDialog(":/dialog-save", QPoint(200, 77),
                                     QPoint(600, 477), scene(), background);

    pointBg = new ButtonItem(":/editor-point", QPoint(68, 47),
                             QPoint(112, 93), scene(), background);

    lineBg = new ButtonItem(":/editor-line", QPoint(66, 155),
                             QPoint(114, 201), scene(), background);

    loadBg = new ButtonItem(":/editor-load", QPoint(72, 256),
                             QPoint(119, 302), scene(), background);

    saveBg = new ButtonItem(":/editor-save", QPoint(66, 367),
                             QPoint(112, 416), scene(), background);

    returnBg = new ButtonItem(":/editor-return", QPoint(69, 477),
                             QPoint(116, 521), scene(), background);

    canvas = new Canvas(QString(), QPoint(182, 94), QPoint(754, 500), scene(), background);
}

void LevelEditor::initEventSystem()
{
    connect(returnBg, SIGNAL(clicked(ButtonItem*)), this, SLOT(clicked(ButtonItem*)));
    connect(pointBg, SIGNAL(clicked(ButtonItem*)), this, SLOT(clicked(ButtonItem*)));
    connect(lineBg, SIGNAL(clicked(ButtonItem*)), this, SLOT(clicked(ButtonItem*)));
    connect(saveBg, SIGNAL(clicked(ButtonItem*)), this, SLOT(clicked(ButtonItem*)));
    connect(loadBg, SIGNAL(clicked(ButtonItem*)), this, SLOT(clicked(ButtonItem*)));
    connect(saveDialog, SIGNAL(dialogClosed()), this, SLOT(dialogClosed()));
    connect(saveDialog, SIGNAL(saveClicked(QString)), this, SLOT(doSaveClicked(QString)));

    connect(canvas, SIGNAL(linerHoverEnter()), this, SLOT(linerHoverEntered()));
    connect(canvas, SIGNAL(linerHoverLeave()), this, SLOT(linerHoverLeft()));
    connect(canvas, SIGNAL(lineHoverEnter()), this, SLOT(lineHoverEntered()));
    connect(canvas, SIGNAL(lineHoverLeave()), this, SLOT(lineHoverLeft()));
    connect(canvas, SIGNAL(pointHoverEnter()), this, SLOT(pointHoverEntered()));
    connect(canvas, SIGNAL(pointHoverLeave()), this, SLOT(pointHoverLeft()));
    connect(canvas, SIGNAL(canvasHoverEnter(CanvasState)),
            this, SLOT(canvasHoverEntered(CanvasState)));
    connect(canvas, SIGNAL(canvasHoverLeave()), this, SLOT(canvasHoverLeft()));
    connect(canvas, SIGNAL(pointDragStart()), this, SLOT(pointDragStarted()));
    connect(canvas, SIGNAL(pointDragStop()), this, SLOT(pointDragStoped()));
    connect(canvas, SIGNAL(lineDragStart()), this, SLOT(lineDragStarted()));
    connect(canvas, SIGNAL(lineDragStop()), this, SLOT(lineDragStoped()));
}

void LevelEditor::dialogClosed()
{
    saveBg->setFocusing(false);
    enableButtons(true);
}

void LevelEditor::lineHoverEntered()
{
    emit lineHoverEnter();
}

void LevelEditor::lineHoverLeft()
{
    emit lineHoverLeave();
}

void LevelEditor::linerHoverEntered()
{
    emit linerHoverEnter();
}

void LevelEditor::linerHoverLeft()
{
    emit linerHoverLeave();
}

void LevelEditor::pointHoverEntered()
{
    emit pointHoverEnter();
}

void LevelEditor::pointHoverLeft()
{
    emit pointHoverLeave();
}

void LevelEditor::canvasHoverEntered(CanvasState state)
{
    emit canvasHoverEnter(state);
}

void LevelEditor::canvasHoverLeft()
{
    emit canvasHoverLeave();
}

void LevelEditor::pointDragStarted()
{
    emit pointDragStart();
}

void LevelEditor::pointDragStoped()
{
    emit pointDragStop();
}

void LevelEditor::lineDragStarted()
{
    emit lineDragStart();
}

void LevelEditor::lineDragStoped()
{
    emit lineDragStop();
}

void LevelEditor::lineringStoped()
{
    emit lineringStop();
}

void LevelEditor::doSaveClicked(const QString &name)
{
    saveToCurrentLevel(name);
    enableButtons(true);
    emit saveClicked(name);
}

void LevelEditor::saveToCurrentLevel(const QString &name)
{

    if (currentLevel==NULL)
    {
        currentLevel = new Level(-1, name);
        canvas->setNameBanner(name);
    }
    currentLevel->clear();

    QHash<Point*, Point*> convertMap;
    QLinkedList<Point*> pl = canvas->getPointsList();
    QLinkedList<Line*> ll = canvas->getLinesList();

    QLinkedList<Point *>::const_iterator pit;
    for (pit=pl.begin(); pit!=pl.end(); pit++) {
        Point* p = new Point(*(*pit));
        scene()->removeItem(p);
        p->setParentItem(NULL);
        convertMap[*pit] = p;
        currentLevel->addPoint(p);
    }

    QLinkedList<Line *>::const_iterator lit;
    for (lit=ll.begin(); lit!=ll.end(); lit++) {
        Line* l = new Line(*(*lit));
        l->setStartPoint(convertMap[(*lit)->getStartPoint()]);
        if ((*lit)->getEndPoint() != NULL)
            l->setEndPoint(convertMap[(*lit)->getEndPoint()]);
        scene()->removeItem(l);
        l->setParentItem(NULL);
        currentLevel->addLine(l);
    }
}

void LevelEditor::clicked(ButtonItem *who)
{
    if (returnBg == who) {
        emit returnClicked();
        if (currentLevel != NULL && currentLevel->getId()==-1)
            delete currentLevel;
        canvas->clear();
        canvas->setNameBanner("[untitled]");
    } else if (lineBg == who) {
        emit lineClicked();
        canvas->setState(commons::LINE);
    } else if (pointBg == who) {
        emit pointClicked();
        canvas->setState(commons::POINT);
    } else if (saveBg == who) {
        enableButtons(false);
        saveDialog->popup();
    } else if (loadBg == who) {
        canvas->clear();
        emit loadClicked();
    }
}

void LevelEditor::enableButtons(bool enabled)
{
    pointBg->setEnabled(enabled);
    lineBg->setEnabled(enabled);
    saveBg->setEnabled(enabled);
    loadBg->setEnabled(enabled);
    returnBg->setEnabled(enabled);
    canvas->setEnabled(enabled);
}

void LevelEditor::setEditingLevel(Level *level)
{
    currentLevel = level;

    if (level == NULL)
    {
        canvas->copyGraph(QLinkedList<Point*>(), QLinkedList<Line*>());
        return;
    }
    else
        canvas->copyGraph(level->getPointsList(), level->getLinesList());
    canvas->setNameBanner(level->getName());
}

//const QLinkedList<Point*>& LevelEditor::getPointsList()
//{
//    return canvas->getPointsList();
//}

//const QLinkedList<Line*>& LevelEditor::getLinesList()
//{
//    return canvas->getLinesList();
//}
